import time
import os
from datetime import datetime
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from minio import Minio
from minio.error import S3Error


# 初始化 MinIO 客户端
minio_client = Minio(
     "8.137.58.206:9000",
    access_key= "9eBv4Rt6",
    secret_key= "3a7W5Mz8",
    secure= False
)
watch_paths = [
            "C:/Users/96523/Downloads/test",
            "C:/Users/96523/Downloads/test1",
            "C:/Users/96523/Downloads/test2"
        ]

class ImageUploadHandler(FileSystemEventHandler):
    def __init__(self):
        self.retry_queue = []
        self.extensions =  [".jpg", ".png", ".jpeg", ".bmp"]
        self.stable_check_interval =  1
        self.max_stable_wait = 10
        self.max_retries = 3
        self.bucket_name = "bucket1"

        # 确保MinIO桶存在
        self.ensure_bucket_exists(self.bucket_name)
        print("初始化监控器")

    def ensure_bucket_exists(self, bucket_name):
        try:
            if not minio_client.bucket_exists(bucket_name):
                minio_client.make_bucket(bucket_name)
                print(f"创建桶: {bucket_name}")
            else:
                print(f"桶已存在: {bucket_name}")
        except S3Error as err:
            print(f"检查桶失败: {err}")

    def wait_for_file_stable(self, file_path):
        """等待文件大小稳定"""
        size = -1
        wait_time = 0
        while wait_time < self.max_stable_wait:
            try:
                current_size = os.path.getsize(file_path)
            except OSError:
                current_size = -1
            if current_size == size:
                return True
            size = current_size
            time.sleep(self.stable_check_interval)
            wait_time += self.stable_check_interval
        return False

    def on_created(self, event):
        file_path = event.src_path
        if not event.is_directory and any(file_path.lower().endswith(ext) for ext in self.extensions):
            print(f"检测到新文件: {file_path}")
            # 等待文件完全写入
            if self.wait_for_file_stable(file_path):
                self.upload_file(file_path)
            else:
                print(f"文件未稳定，放弃上传: {file_path}")

    def upload_file(self, file_path):
        for attempt in range(self.max_retries):
            timestamp = str(int(time.time()))
            # 保留原始文件扩展名
            original_ext = os.path.splitext(file_path)[1].lower()
            original_filename = os.path.basename(file_path)   # 原图名字
            # 根据文件路径生成对象名，包含文件夹信息
            folder_name = os.path.basename(os.path.dirname(file_path))
            # object_name = f"{folder_name}/{timestamp}{original_ext}"
            object_name = f"{folder_name}/{original_filename}"
            try:
                minio_client.fput_object(
                    self.bucket_name,
                    object_name,
                    file_path,
                )
                print(f"图片 {file_path} 已成功上传为对象 {object_name}")
                os.remove(file_path)  # 删除本地文件
                return True
            except S3Error as err:
                print(f"MinIO上传失败（尝试 {attempt + 1}/{self.max_retries}）: {err}")
            except Exception as e:
                print(f"上传异常（尝试 {attempt + 1}/{self.max_retries}）: {e}")
            # time.sleep(2 ** attempt)  # 指数退避
            time.sleep(2 * attempt)  # 线性退避

        print(f"放弃上传，保留文件: {file_path}")
        return False


def ensure_directory_exists(directory_path):
    """确保目录存在，如果不存在则创建"""
    if not os.path.exists(directory_path):
        try:
            os.makedirs(directory_path, exist_ok=True)
            print(f"创建目录: {directory_path}")
            return True
        except Exception as e:
            print(f"创建目录失败 {directory_path}: {e}")
            return False
    else:
        print(f"目录已存在: {directory_path}")
        return True

def start_monitoring():
    """开始监控多个目录"""
    observer = Observer()
    event_handler = ImageUploadHandler()

    # 确保所有监控路径都存在
    valid_watch_paths = []
    for watch_path in watch_paths:
        if ensure_directory_exists(watch_path):
            valid_watch_paths.append(watch_path)
        else:
            print(f"无法创建监控路径，跳过: {watch_path}")

    # 监控所有有效路径
    for watch_path in valid_watch_paths:
        observer.schedule(event_handler, watch_path, recursive=False)
        print(f"开始监控目录: {watch_path}")

    if not valid_watch_paths:
        print("没有有效的监控路径，程序退出")
        return

    observer.start()
    print(f"总共监控 {len(watch_paths)} 个目录")

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
        print("监控已停止")
    observer.join()


# 使用示例
if __name__ == "__main__":
    start_monitoring()